/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package yoga.algo.coding.floating;

import yoga.algo.coding.ICoding;
import yoga.algo.coding.ICodingOperator;
import yoga.probability.Probablistics;

public class FloatingPointCoding<T> implements ICoding<T>
{
    private FloatDataArray m_floatDataArray;
    private double LowerBoundary = Double.MIN_VALUE;
    private double UpperBoundary = Double.MAX_VALUE;
    private double MutationRange = 10.0;
    private int NumberOfArguments;
    
    
    public FloatingPointCoding(FloatDataArray floatDataArray)
    {
        this.m_floatDataArray = floatDataArray;
    }

    public FloatDataArray getData()
    {
        return m_floatDataArray;
    }

    public void setData(FloatDataArray floatDataArray)
    {
        m_floatDataArray = floatDataArray;
    }
    
    public void setNumberOfArguments(int number)
    {
        NumberOfArguments = number;
    }
    
    public int getNumberOfArguments()
    {
        return NumberOfArguments;
    }

    /**
     * Get the value of UpperBoundary
     *
     * @return the value of UpperBoundary
     */
    public double getUpperBoundary()
    {
        return UpperBoundary;
    }

    /**
     * Set the value of UpperBoundary
     *
     * @param UpperBoundary new value of UpperBoundary
     */
    public void setUpperBoundary(double UpperBoundary)
    {
        this.UpperBoundary = UpperBoundary;
    }

    /**
     * Get the value of LowerBoundary
     *
     * @return the value of LowerBoundary
     */
    public double getLowerBoundary()
    {
        return LowerBoundary;
    }

    /**
     * Set the value of LowerBoundary
     *
     * @param LowerBoundary new value of LowerBoundary
     */
    public void setLowerBoundary(double LowerBoundary)
    {
        this.LowerBoundary = LowerBoundary;
    }

//
//    #Region ICoding
//
    @Override
    public void mutate(MutationTypes mutationType, double probability) throws UnsupportedOperationException
    {

        if (Probablistics.randomBoolean(probability))
        {
            if (mutationType.equals(MutationTypes.Single))
            {
                m_floatDataArray.contaminatedRandomFloatNumber(MutationRange);
            }
            else
            {
                m_floatDataArray.contaminatedRandomFloatNumber(MutationRange);
                m_floatDataArray.contaminatedRandomFloatNumber(MutationRange);
                //m_floatDataArray.contaminatedRandomFloatNumber(LowerBoundary, UpperBoundary);
                //m_floatDataArray.contaminatedRandomFloatNumber(LowerBoundary, UpperBoundary);
            }
        }

    }

    @Override
    public void crossWith(CrossingTypes crossingType, ICoding<T> coding) throws UnsupportedOperationException, IllegalArgumentException
    {
        if (!coding.getClass().isInstance(this))
        {
            throw new IllegalArgumentException("Type missmatch, cannot cross " + this.getClass().getName() + " with supplied coding reference");
        }
        FloatingPointCoding<T> floatingPointCoding = (FloatingPointCoding<T>) coding;


        if (crossingType.equals(CrossingTypes.Single))
        {
            int crossingIndex = Probablistics.getRandomInt(m_floatDataArray.size());
            m_floatDataArray.swapFloatRangeWith(floatingPointCoding.m_floatDataArray, crossingIndex, m_floatDataArray.size() - 1);
        }
        else
        {
            int crossingFirstIndex = Probablistics.getRandomInt(m_floatDataArray.size());
            m_floatDataArray.swapFloatRangeWith(floatingPointCoding.m_floatDataArray, crossingFirstIndex, m_floatDataArray.size() - 1);

            int crossingSecondIndex = crossingFirstIndex + Probablistics.getRandomInt(m_floatDataArray.size() - crossingFirstIndex);
            m_floatDataArray.swapFloatRangeWith(floatingPointCoding.m_floatDataArray, crossingSecondIndex, m_floatDataArray.size() - 1);
        }

    }

    @Override
    public void invert(InversionTypes inversionType) throws UnsupportedOperationException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void reorder(OrderingTypes orderingType) throws UnsupportedOperationException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void runOperator(ICodingOperator<T> codingOperator) throws Exception
    {
        codingOperator.run(this);
    }

    @Override
    public ICoding<T> getCopy()
    {
        FloatingPointCoding<T> codingClone = new FloatingPointCoding<T>(m_floatDataArray.getCopy());
        codingClone.LowerBoundary = this.LowerBoundary;
        codingClone.UpperBoundary = this.UpperBoundary;
        codingClone.NumberOfArguments = this.NumberOfArguments;
                
        return codingClone;
    }

    @Override
    public String getDescription()
    {
        return "FloatPointCoding";
    }

    @Override
    public int getSchemataHash()
    {
        double hashDouble = 0;
        double[] floatArray = m_floatDataArray.getFloatDataArray();
                
        for (int i=0; i < m_floatDataArray.size(); i++)
        {
            hashDouble += floatArray[i]  + Math.pow(10,i);
        }
                
        return (int) hashDouble;
    }
}
